package com.whales.shared.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.multipart.MultipartFile;

public class FileUtil {

    /**
     * Default characterSet으로 파일생성.
     * @메소드명 : writeFile   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param fileName
     * @param contents
     * @throws Exception	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static void writeFile(String fileName, String contents) throws Exception {
        writeFile(fileName, contents, null, false);
    }

    public static void writeFile(String fileName, String contents, boolean append) throws Exception {
        writeFile(fileName, contents, null, append);
    }

    public static void writeFile(String fileName, String contents, String encodingType) throws Exception {
        writeFile(fileName, contents, null, false);
    }
    
    /**
     * 파일의 확장자를 반환한다.
     * @메소드명 : getExtName   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param fileName
     * @return	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static String getExtName(String fileName) {
        if (fileName == null)
            return null;

        String[] fileNameArr = fileName.split("[.]");

        if (fileNameArr.length == 1)
            return fileName;

        return "." + fileNameArr[fileNameArr.length-1];
    }

    /**
     * 원하는 encodingType으로 파일생성
     * @메소드명 : writeFile   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param fileName
     * @param contents
     * @param encodingType
     * @param append
     * @throws Exception	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static void writeFile(String fileName, String contents, String encodingType, boolean append) throws Exception {

        FileOutputStream fileOutputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        BufferedWriter bufferedWriter = null;

        try {
            fileOutputStream = new FileOutputStream(fileName, append);

            // OutputStreamWriter 클래스에서 아규먼트가 2개인 생성자에서 2번째 charset이 null 일 경우 Exception 처리 되어 있어서..
            // overload 하지 못하고 별도로 처리함...
            if (encodingType == null) {
                outputStreamWriter = new OutputStreamWriter(fileOutputStream);

            } else {
                outputStreamWriter = new OutputStreamWriter(fileOutputStream, encodingType); // 한자를 지원하기 위해 UTF-8형식으로 파일 생성
            }
            bufferedWriter = new BufferedWriter(outputStreamWriter);

            bufferedWriter.write(contents);
            bufferedWriter.flush();

        } finally {
            try {
                bufferedWriter.close();
                outputStreamWriter.close();
                fileOutputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        } // end finally
    }

    /**
     * 로컬 파일을 서버에 업로드(복사)하는 메소드
     * @메소드명 : saveFile   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param multipartFile
     * @param fileFullPath
     * @return	true 이면 저장 성공, 그렇지 않으면 false
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static boolean saveFile(MultipartFile multipartFile, String fileFullPath) {
        if (makeFile(multipartFile, fileFullPath) == null)
            return false;
        return true;
    }    
    

    /**
     * 로컬 파일을 서버에 업로드(복사)하는 메소드
     * @메소드명 : makeFile   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param multipartFile
     * @param fileFullPath
     * @return	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static File makeFile(MultipartFile multipartFile, String fileFullPath) {
                
        File file = null;
        try {
            //디렉토리 생
            FileUtil.makeDirectory(fileFullPath);
            
            file = new File(fileFullPath);
            if(multipartFile!=null){
                multipartFile.transferTo(file);
            }
            
            return file;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 파일 삭제
     * @메소드명 : removeFile   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param fileFullPath	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static void removeFile(String fileFullPath) {
        File file = null;
        
        try {
            file = new File(fileFullPath);
            if(file.exists())
                file.delete();
            else
                throw new FileNotFoundException("파일을 찾을 수 없습니다.");
        }catch(Exception e){
            e.printStackTrace();
        }        
    }

    /**
     * Temp 폴더에 있는 파일을 옮겨준다.
     * @author swpark
     * @date Jun 18, 2008
     * @param multipartFile
     * @param filePath
     * @param fileName
     * @return
     */
    public static boolean moveTempFile(String tempName, String targetName) {

        try {
            BufferedInputStream fis = new BufferedInputStream(new FileInputStream(new File(tempName)), 1024);
            BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(targetName), 1024);

            byte buffer[] = new byte[1024];
            int readByte = 0;

            while ((readByte = fis.read(buffer, 0, 1024)) >= 0) {
                fos.write(buffer, 0, readByte);
            }

            fis.close();
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 파일 다운로드 Util
     * @메소드명 : fileDownload   					   
     * @작성자 : sw775.park   
     * @작성일 : Jul 23, 2009
     * @param file
     * @param response
     * @throws Exception	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static void fileDownload(File file, String fileName, HttpServletResponse response) throws Exception {
        OutputStream os = null;
        FileInputStream is = null;
        try {
            byte[] buf = new byte[8 * 1024];
            is = new FileInputStream(file);

            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName,"UTF-8") + "\"");
            response.setHeader("Content-Length", "" + file.length());

            os = response.getOutputStream();
            for (int i = 0; (i = is.read(buf, 0, buf.length)) != -1;) {
                os.write(buf, 0, i);
            }
            os.flush();

        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            try {
                if (is != null)
                    is.close();
                if (os != null)
                    os.close();
            } catch (Exception e) {
            }
        }
    }

    /**
     * @메소드명 : urlFileDownload   					   
     * @작성자 : sw775.park   
     * @작성일 : Jun 18, 2009
     * @param urlPath
     * @param fileName
     * @param response	
     * @설명 : URL을 통한 파일 다운로드
     * @수정이력 - 수정일,수정자,수정내용					   
     *										   
     */
    public static void urlFileDownload(String urlPath, String fileName, HttpServletResponse response) {
        InputStream inData = null;
        OutputStream outFile = null;
        byte data[];
        try {
            URL url = new URL(urlPath);
            URLConnection connection = url.openConnection();
            int size = connection.getContentLength();

            inData = connection.getInputStream();
            outFile = response.getOutputStream();
            data = new byte[1024];

            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            response.setHeader("Content-Length", "" + size);

            int n = 0;
            while ((n = inData.read(data)) != -1) {
                outFile.write(data, 0, n);
            }
            outFile.flush();

            inData.close();
            outFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inData != null)
                    inData.close();
                if (outFile != null)
                    outFile.close();
            } catch (Exception e) {
            }
        }

    }
    
    /**
     * URL의 파일을 savePath에 저장
     * @메소드명 : urlFileDownload                         
     * @작성자 : sw775.park   
     * @작성일 : Jun 18, 2009
     * @param urlPath
     * @param savePath
     * @param saveFileName
     * @설명 : URL을 통한 원격 파일 다운로드
     * @수정이력 - 수정일,수정자,수정내용                    
     *                                         
     */
    public static String getUrlFile(String urlPath, String savePath, String saveFileName) {
        InputStream inData = null;
        BufferedOutputStream outFile = null;
        byte data[];
        String fileName = null;
        
        try {
            URL url = new URL(urlPath);
            URLConnection connection = url.openConnection();
            connection.setDoOutput(true);

            inData = connection.getInputStream();  
            fileName = FileUtil.getUrlFileName4Header(connection);          
            //디렉토리 생성
            FileUtil.makeDirectory(savePath);
            
            outFile = new BufferedOutputStream(new FileOutputStream(savePath + saveFileName + FileUtil.getExtName(fileName)), 1024);
            data = new byte[1024];

            int n = 0;
            while ((n = inData.read(data)) != -1) {
                outFile.write(data, 0, n);
            }
            
            outFile.flush();
            inData.close();
            outFile.close();
            
            return fileName;
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inData != null)
                    inData.close();
                if (outFile != null)
                    outFile.close();
            } catch (Exception e) {
            }
        }
        
        return fileName;
    }
    
    /**
     * 파일 디렉토르 생성
     * @메소드명 : makeDirectory   					   
     * @작성자 : sw775.park   
     * @작성일 : Nov 9, 2009
     * @param fileFullPath
     * @throws Exception	
     * @설명 :
     * @수정이력 - 수정일,수정자,수정내용					   
     *
     */
    public static void makeDirectory(String fileFullPath) throws Exception{
        String directory = fileFullPath.substring(0, fileFullPath.lastIndexOf("\\"));
        File file = new File(directory);
        if(!file.exists()){
            file.mkdirs();
        }
    }
    
    public static boolean deleteDirectory(String directory) {
    	File path = new File(directory);
        if(!path.exists()) {
            return false;
        }
         
        File[] files = path.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
            	deleteDirectory(file.getAbsolutePath());
            } else {
                file.delete();
            }
        }
         
        return path.delete();
    }
    
    public static String getUrlFileName4Header(URLConnection connection) throws Exception{        
        String returnFileName = "";
        String header = connection.getHeaderField("Content-Disposition");
        int filenameIndex = 0; 
        
        if(header != null){
            filenameIndex = header.lastIndexOf("filename=");
            returnFileName = header.substring((filenameIndex)+9,(header.length() - 1));
            return returnFileName;
        }
        
        return returnFileName;
    }
}
